"use strict";

const DbMixin = require("../mixins/db.mixin");

/**
 * @typedef {import('moleculer').ServiceSchema} ServiceSchema Moleculer's Service Schema
 * @typedef {import('moleculer').Context} Context Moleculer's Context
 */

/** @type {ServiceSchema} */
module.exports = {
    name: "settings",

    /**
     * Mixins
     */
    mixins: [DbMixin("settings")],

    /**
     * Settings
     */
    settings: {
        // Available fields in the responses
        fields: [
            "_id",
            "key",
            "value",
            "createdAt",
            "updatedAt"
        ],
        // Validator for the `create` & `insert` actions.
        entityValidator: {
            key: "string",
            value: "any"
        }
    },

    /**
     * Dependencies
     */
    dependencies: [],

    /**
     * Actions
     */
    actions: {
        /**
         * Get all system settings
         * 
         * @returns {Object} System settings as key-value pairs
         */
        getAll: {
            rest: "GET /",
            cache: false,
            async handler(ctx) {
                try {
                    const settings = await this.adapter.find({});

                    // 将设置转换为键值对对象
                    const settingsObj = settings.reduce((acc, setting) => {
                        acc[setting.key] = setting.value;
                        return acc;
                    }, {});

                    return {
                        code: 200,
                        data: settingsObj,
                        message: "success"
                    };
                } catch (error) {
                    this.logger.error("获取系统设置失败", error);
                    return {
                        code: 500,
                        data: null,
                        message: "获取系统设置失败: " + error.message
                    };
                }
            }
        },

        /**
         * Get a specific setting by key
         * 
         * @param {String} key - Setting key
         * @returns {Object} Setting value
         */
        get: {
            rest: "GET /:key",
            cache: false,
            params: {
                key: "string"
            },
            async handler(ctx) {
                try {
                    const { key } = ctx.params;
                    const setting = await this.adapter.findOne({ key });

                    if (!setting) {
                        return {
                            code: 404,
                            data: null,
                            message: `设置 '${key}' 不存在`
                        };
                    }

                    return {
                        code: 200,
                        data: setting.value,
                        message: "success"
                    };
                } catch (error) {
                    this.logger.error(`获取设置 '${ctx.params.key}' 失败`, error);
                    return {
                        code: 500,
                        data: null,
                        message: "获取设置失败: " + error.message
                    };
                }
            }
        },

        /**
         * Set a specific setting
         * 
         * @param {String} key - Setting key
         * @param {any} value - Setting value
         * @returns {Object} Updated setting
         */
        set: {
            rest: "POST /:key",
            cache: false,
            params: {
                key: "string",
                value: "any"
            },
            async handler(ctx) {
                try {
                    const { key, value } = ctx.params;

                    // 查找是否已存在该设置
                    const existingSetting = await this.adapter.findOne({ key });

                    let result;
                    if (existingSetting) {
                        // 更新现有设置
                        result = await this.adapter.updateById(existingSetting._id, {
                            $set: { value, updatedAt: new Date() }
                        });
                    } else {
                        // 创建新设置
                        result = await this.adapter.insert({
                            key,
                            value,
                            createdAt: new Date(),
                            updatedAt: new Date()
                        });
                    }

                    return {
                        code: 200,
                        data: { key, value },
                        message: "设置保存成功"
                    };
                } catch (error) {
                    this.logger.error(`保存设置 '${ctx.params.key}' 失败`, error);
                    return {
                        code: 500,
                        data: null,
                        message: "保存设置失败: " + error.message
                    };
                }
            }
        },

        /**
         * Update multiple settings at once
         * 
         * @param {Object} settings - Key-value pairs of settings to update
         * @returns {Object} Updated settings
         */
        updateMultiple: {
            rest: "PUT /",
            cache: false,
            params: {
                settings: "object"
            },
            async handler(ctx) {
                try {
                    const { settings } = ctx.params;
                    const updatedSettings = {};

                    // 批量更新设置
                    for (const [key, value] of Object.entries(settings)) {
                        const existingSetting = await this.adapter.findOne({ key });

                        if (existingSetting) {
                            // 更新现有设置
                            await this.adapter.updateById(existingSetting._id, {
                                $set: { value, updatedAt: new Date() }
                            });
                        } else {
                            // 创建新设置
                            await this.adapter.insert({
                                key,
                                value,
                                createdAt: new Date(),
                                updatedAt: new Date()
                            });
                        }

                        updatedSettings[key] = value;
                    }

                    return {
                        code: 200,
                        data: updatedSettings,
                        message: "设置批量更新成功"
                    };
                } catch (error) {
                    this.logger.error("批量更新设置失败", error);
                    return {
                        code: 500,
                        data: null,
                        message: "批量更新设置失败: " + error.message
                    };
                }
            }
        },

        /**
         * Delete a specific setting
         * 
         * @param {String} key - Setting key to delete
         * @returns {Object} Result of deletion
         */
        delete: {
            rest: "DELETE /:key",
            cache: false,
            params: {
                key: "string"
            },
            async handler(ctx) {
                try {
                    const { key } = ctx.params;
                    const setting = await this.adapter.findOne({ key });

                    if (!setting) {
                        return {
                            code: 404,
                            data: null,
                            message: `设置 '${key}' 不存在`
                        };
                    }

                    await this.adapter.removeById(setting._id);

                    return {
                        code: 200,
                        data: null,
                        message: "设置删除成功"
                    };
                } catch (error) {
                    this.logger.error(`删除设置 '${ctx.params.key}' 失败`, error);
                    return {
                        code: 500,
                        data: null,
                        message: "删除设置失败: " + error.message
                    };
                }
            }
        },

        /**
         * Get system settings (for blog frontend)
         * 
         * @returns {Object} Formatted system settings
         */
        getSystemSettings: {
            cache: false,
            async handler(ctx) {
                try {
                    const settings = await this.adapter.find({});
                    const settingsObj = settings.reduce((acc, setting) => {
                        acc[setting.key] = setting.value;
                        return acc;
                    }, {});

                    // 返回格式化的系统设置
                    return {
                        code: 200,
                        data: {
                            siteName: settingsObj.siteName || "Gulu Blog",
                            description: settingsObj.description || "专注于前端技术分享的博客",
                            keywords: settingsObj.keywords || "Vue.js,React,JavaScript,前端开发",
                            recordInfo: settingsObj.recordInfo || {
                                icpLink: "https://beian.miit.gov.cn/",
                                icp: "京ICP备12345678号-1",
                                isShowIcp: true,
                                beianLink: "http://www.beian.gov.cn/portal/registerSystemInfo",
                                beian: "京公网安备12345678901234号",
                                isShowBeian: true,
                                company: "Gulu科技有限公司",
                                isShowCompany: true,
                                copyright: "© 2023 Gulu Blog. All rights reserved.",
                                isShowCopyright: true,
                            }
                        },
                        message: "success"
                    };
                } catch (error) {
                    this.logger.error("获取系统设置失败", error);
                    return {
                        code: 500,
                        data: null,
                        message: "获取系统设置失败: " + error.message
                    };
                }
            }
        },

        /**
         * Update system settings
         * 
         * @param {Object} settings - System settings to update
         * @returns {Object} Updated system settings
         */
        updateSystemSettings: {
            rest: "PUT /system",
            cache: false,
            params: {
                siteName: "string|optional",
                description: "string|optional",
                keywords: "string|optional",
                recordInfo: "object|optional",
            },
            async handler(ctx) {
                try {
                    const updates = ctx.params;
                    const updatedSettings = {};

                    // 批量更新系统设置
                    for (const [key, value] of Object.entries(updates)) {
                        if (value !== undefined) {
                            const existingSetting = await this.adapter.findOne({ key });

                            if (existingSetting) {
                                await this.adapter.updateById(existingSetting._id, {
                                    $set: { value, updatedAt: new Date() }
                                });
                            } else {
                                await this.adapter.insert({
                                    key,
                                    value,
                                    createdAt: new Date(),
                                    updatedAt: new Date()
                                });
                            }

                            updatedSettings[key] = value;
                        }
                    }

                    return {
                        code: 200,
                        data: updatedSettings,
                        message: "系统设置更新成功"
                    };
                } catch (error) {
                    this.logger.error("更新系统设置失败", error);
                    return {
                        code: 500,
                        data: null,
                        message: "更新系统设置失败: " + error.message
                    };
                }
            }
        }
    },

    /**
     * Methods
     */
    methods: {},

    /**
     * Events
     */
    events: {},

    /**
     * Service created lifecycle event handler
     */
    created() { },

    /**
     * Service started lifecycle event handler
     */
    async started() {
        // Seed some mock data if needed
    },

    /**
     * Service stopped lifecycle event handler
     */
    async stopped() { }
};